from Tkinter import *
import tkFileDialog
import tkFont
import random


class TorrentListPanel (Frame):
	def __init__ (self, root):
		Frame.__init__( self, root, relief="sunken", border=5 )

		# top row - label and button
		self.labelFrame = Frame( self )
		self.labelFrame.pack(fill=X)

		self.listLabel = Label(self.labelFrame, text="Active Torrents")
		self.listLabel.pack(side=LEFT)
		
		# next, the list of torrents
		self.torrentList = Listbox( self, selectmode=SINGLE )
		self.torrentList.pack(fill=BOTH, expand=True)

		self.scrollbar = Scrollbar( self.torrentList, orient=VERTICAL )
		self.scrollbar.pack(side=RIGHT, fill=Y)

		# bind the scrollbar to the list
		self.scrollbar.config(command=self.torrentList.yview)
		self.torrentList.config(yscrollcommand=self.scrollbar.set)

		# this is a hackedy listener on the selection
		self.selectedTorrent = None
		self.pollSelectedTorrent()
		

	def pollSelectedTorrent (self):
		currentSelection = self.torrentList.curselection()
		if len(currentSelection) > 0:
			currentSelection = int(currentSelection[0])
			if currentSelection != self.selectedTorrent:
				self.selectedTorrent = currentSelection
				self.master.selectTorrent( currentSelection )
		self.after(250, self.pollSelectedTorrent)

	def addTorrentToList (self, torrent):
		self.torrentList.insert( END, torrent.metaInfo["info"]["name"] )
		self.torrentList.selection_clear( 0, END )
		self.torrentList.selection_set( END )
		


class TorrentDisplayPanel (Frame):
	def __init__ (self, root, torrent):
		Frame.__init__(self, root, relief="sunken", border=5)
		
		self.torrent = torrent

		# torrent title
		self.title = Label(self, text=self.torrent.metaInfo["info"]["name"] )
		self.title.grid( row=0, column=0, columnspan=3, sticky=W )

		# stats
		self.statUp = Label(self, text="" )
		self.statUp.grid( row=1, column=0, sticky=W )
		
		self.statDown = Label(self, text="" )
		self.statDown.grid( row=1, column=1, sticky=W )

		self.statRemain = Label(self, text="" )
		self.statRemain.grid( row=1, column=2, sticky=W )

		# contact tracker button
		self.getMorePeers = Button(self, text="get more peers", command=self.torrent.contactTracker)
		self.getMorePeers.grid(row=0, column=2)

		# pieces	
		self.pieceDisplayMaxSize = 200
		self.pieceDisplay = Canvas( self )
		self.pieceDisplay.grid( row=2, column=0, columnspan=3, sticky=N+E+S+W )

		self.pieceScrollbar = Scrollbar( self, orient=VERTICAL )
		self.pieceScrollbar.grid(row=2, column=3, sticky=N+S+W)

		# bind the scrollbar to the canvas
		self.pieceScrollbar.config(command=self.pieceDisplay.yview)
		self.pieceDisplay.config(yscrollcommand=self.pieceScrollbar.set)

		# set up the resizing
		self.pieceDisplay.bind("<Configure>", self.redoPieceDisplay)
		self.grid_columnconfigure( 2, weight=1 )

		self.grid_rowconfigure( 2, minsize=150, weight=1 )
		self.grid_rowconfigure( 3, minsize=300, weight=2 )
		


		font = tkFont.Font(family="Courier", size=10)
		self.peerList = Listbox( self, selectmode=SINGLE, font=font )
		self.peerList.grid( row=3, column=0, columnspan=3, sticky=N+E+S+W )

		self.peerListScrollbar = Scrollbar( self, orient=VERTICAL )
		self.peerListScrollbar.grid(row=3, column=3, sticky=N+S+W)

		self.peerListScrollbar.config(command=self.peerList.yview)
		self.peerList.config(yscrollcommand=self.peerListScrollbar.set)


		self.visible = False
		self.redoPieceDisplay()
		self.refresh()


	def scrollAllPeerLists (self, *params ):
		for listbox in self.peerList_listboxes:
			listbox.yview( params[0], params[1] )

	def refresh (self):
		if self.visible:
			with self.torrent.lock:
				self.updateStats()
				self.recolorPieceDisplay()
				self.updatePeerList()
		self.after(500, self.refresh)

	def updateStats (self):
		self.statUp.config( text="uploaded: " + str(self.torrent.uploaded) )
		self.statDown.config( text="downloaded: " + str(self.torrent.downloaded) )
		self.statRemain.config( text="remaining: " + str(self.torrent.remaining) )

	def recolorPieceDisplay (self):
		for i in range(self.torrent.pieceCount):
			ID = self.pieceDisplayIndices[i]
			color = "blue" if self.torrent.pieceComplete[i] else "red"
			self.pieceDisplay.itemconfig( ID, fill=color )		

	def redoPieceDisplay (self, event = None):
		self.pieceDisplay.delete(ALL)
		self.pieceDisplayIndices = []

		pieceX = 0
		pieceY = 0
		dim = 15
		pad = 2

		for i in range(self.torrent.pieceCount):			
			x = pieceX * (dim + pad)
			y = pieceY * (dim + pad)
			color = "blue" if self.torrent.pieceComplete[i] else "red"
			
			ID = self.pieceDisplay.create_rectangle( x, y, x + dim, y + dim, fill=color, outline="")
			self.pieceDisplayIndices.append( ID )
			
			pieceX += 1
			if ((pieceX+1) * (dim + pad)) > self.pieceDisplay.winfo_width():
				pieceX = 0
				pieceY += 1

		canvasHeight = (pieceY + 1) * (dim + pad)
		self.pieceDisplay.config( scrollregion=(0, 0, 0, canvasHeight) )
		

	def updatePeerList (self):
		for i in range(len(self.torrent.peers)):
			self.peerList.insert( i, self.torrent.peers[i].statusString() )
			self.peerList.delete(i+1)
		self.peerList.delete(len(self.torrent.peers), END)
		self.peerList.insert(0, "     IP address    kb up   kb down   fr up   fr down")



class AppWindow (Tk):
	def __init__ (self, owner):
		Tk.__init__(self)
		self.owner = owner
		self.title = self.owner.localData["id"]
		
		self.geometry( "%dx%d%+d%+d" % (620, 700, 200, 200) )
		self.grid_columnconfigure( 0, minsize=200, weight=1 )
		self.grid_rowconfigure( 1, minsize=100, weight=1 )
		self.grid_rowconfigure( 2, minsize=500, weight=10 )

		self.addTorrentButton = Button(self, text="Add Torrent", command=self.getFile)
		self.addTorrentButton.grid(row=0, column=0, sticky=N+E+S+W)

		self.torrentList = TorrentListPanel( self )
		self.torrentList.grid( row=1, column=0, sticky=N+E+S+W )

		self.torrentDisplayPanels = []
		for torrent in self.owner.torrents:
			self.addTorrent( torrent )
		
		self.mainloop()
		self.owner.kill()


	def addTorrent (self, torrent):		
		torrentDisplay = TorrentDisplayPanel(self, torrent)
		self.torrentDisplayPanels.append( torrentDisplay )
		self.torrentList.addTorrentToList( torrent )

	def selectTorrent (self, index):
		if index >= len(self.torrentDisplayPanels):
			return

		for torrentDisplay in self.torrentDisplayPanels:
			torrentDisplay.grid_remove()

		self.torrentDisplayPanels[index].grid( row=2, column=0, sticky=N+E+S+W )
		self.torrentDisplayPanels[index].visible = True


	def getFile (self):
		filename = tkFileDialog.askopenfilename(
			title='Choose a file', 
			filetypes=[("torrent files","*.torrent")])

		if filename != "":
			torrent = self.owner.addTorrentFromFile( filename )
			if torrent != None:
				self.addTorrent( torrent )





